package fr.istic.linkedcv.server.servicesImpl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import javax.servlet.http.HttpSession;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import fr.istic.linkedcv.client.GroupesCli;
import fr.istic.linkedcv.client.MessageCli;
import fr.istic.linkedcv.client.PersonneCli;
import fr.istic.linkedcv.client.services.PersonneService;
import fr.istic.linkedcv.server.GroupesImpl;
import fr.istic.linkedcv.server.MessagesImpl;
import fr.istic.linkedcv.server.PMF;
import fr.istic.linkedcv.server.PersonneImpl;

public class PersonneServiceImpl extends RemoteServiceServlet implements
		PersonneService {

	/**
	 * 
	 */
	private static final long serialVersionUID = -1101450083921712176L;

	@Override
	public boolean addPersonne(Map<String, String> pers) {
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		try {
			PersonneImpl personne = new PersonneImpl();
			String identifiant = pers.get("identifiant");
			Key key = KeyFactory.createKey(PersonneImpl.class.getSimpleName(),
					identifiant);
			personne.setEncodedKey(key);
			personne.setLogin(identifiant);
			personne.setPassword(pers.get("password"));

			// personne.setGroupesSet(null);
			pm.makePersistent(personne);
		} finally {
			pm.close();
		}

		return true;
	}

	@Override
	public List<PersonneCli> getListePersonnes() {
		List<PersonneCli> listPersonneClis = new ArrayList<PersonneCli>();
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		PersonneImpl pers = getSessionLogin();
		try {
			Query q = pm.newQuery(PersonneImpl.class);
			List<PersonneImpl> listPersonnes = (List<PersonneImpl>) q.execute();
			for (PersonneImpl personne : listPersonnes) {
				if(!personne.getLogin().equals(pers.getLogin())){
					listPersonneClis.add(createPersonneCli(personne));
				}
			}

		} finally {
			pm.close();
		}
		return listPersonneClis;
	}

	public PersonneCli createPersonneCli(PersonneImpl personneImpl) {
		PersonneCli personneCli = new PersonneCli();
		personneCli.setLogin(personneImpl.getLogin());
		personneCli.setPassword(personneImpl.getPassword());
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		try{
			for(Key keyPers : personneImpl.getListeAmis()){
				PersonneImpl ami = pm.getObjectById(PersonneImpl.class, keyPers);
				personneCli.addAmi(ami.getLogin());
			}
			
			for(Key keyGroupe : personneImpl.getGroupesSet()){
				GroupesImpl groupeImpl = pm.getObjectById(GroupesImpl.class,
						keyGroupe);
				personneCli.addGroupe(groupeImpl.getName());
			}
		}finally{
			pm.close();
		}
		
		return personneCli;

	}

	@Override
	public boolean login(Map<String, String> pers) {
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		Boolean res = false;
		HttpSession session = this.getThreadLocalRequest().getSession();

		try {
			String identifiant = pers.get("identifiant");
			Key k = KeyFactory.createKey(PersonneImpl.class.getSimpleName(),
					identifiant);
			PersonneImpl e = pm.getObjectById(PersonneImpl.class, k);
			if (e != null && e.getPassword().equals(pers.get("password"))) {
				res = true;
				session.setAttribute("login", e.getLogin());
			}
			//
		} finally {
			pm.close();
		}
		return res;
	}

	@Override
	public boolean isLogged() {
		HttpSession session = this.getThreadLocalRequest().getSession();
		return session.getAttribute("login") != null;
	}

	@Override
	public boolean createGroupe(Map<String, String> groupe) {
		boolean res = false;
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		HttpSession session = this.getThreadLocalRequest().getSession();
		PersonneImpl personneImpl = pm.getObjectById(PersonneImpl.class,
				(String) session.getAttribute("login"));
		try {
			
			Query query = pm.newQuery(GroupesImpl.class);
			query.setFilter("name == nomGroupe");
			query.declareParameters("String nomGroupe");


			try {
				String nomGroupe = groupe.get("name");
				List<GroupesImpl> results = (List<GroupesImpl>) query.execute(nomGroupe);
				if (results.isEmpty()) {
					
					GroupesImpl groupeImpl = new GroupesImpl();

					groupeImpl.setName(nomGroupe);
					Key key = KeyFactory.createKey(
							GroupesImpl.class.getSimpleName(), nomGroupe);

					groupeImpl.setKey(key);
					groupeImpl.addPersonne(personneImpl);
					pm.makePersistent(groupeImpl);
					res = true;
				}
			} finally {
				query.closeAll();
			}
			

		} finally {
			pm.close();
		}

		return res;
	}

	@Override
	public List<GroupesCli> getListeGroupes() {
		List<GroupesCli> res = new ArrayList<GroupesCli>();
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		PersonneImpl personneLog = getSessionLogin();
		try {
			PersonneImpl personneImpl = pm.getObjectById(PersonneImpl.class,
					personneLog.getLogin());
			List<Key> groupesSet = personneImpl.getGroupesSet();
			for (Key keyGroupe : groupesSet) {
				GroupesImpl groupeImpl = pm.getObjectById(GroupesImpl.class,
						keyGroupe);
				res.add(createGroupeClient(groupeImpl));
			}

		} finally {
			pm.close();
		}
		return res;
	}

	public GroupesCli createGroupeClient(GroupesImpl groupesImpl) {
		GroupesCli groupeCli = new GroupesCli();
		groupeCli.setName(groupesImpl.getName());
		List<Key> personnesSet = groupesImpl.getPersonnesSet();
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();

		try {
			for(Key keyPers : personnesSet){
				PersonneImpl pers = pm.getObjectById(PersonneImpl.class, keyPers);
				groupeCli.addPersonnesSet(pers.getLogin());
			}
		}finally{
			pm.close();
		}
		return groupeCli;
	}

	@Override
	public PersonneCli myAccount() {
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		HttpSession session = this.getThreadLocalRequest().getSession();
		PersonneCli res = null;
		if ((String) session.getAttribute("login") != null) {
			try {
				PersonneImpl personneImpl = pm.getObjectById(
						PersonneImpl.class,
						(String) session.getAttribute("login"));
				res = createPersonneCli(personneImpl);
			} finally {
				pm.close();
			}
		}
		return res;
	}

	@Override
	public boolean addFriend(String friendName) {
		boolean res = false;

		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		HttpSession session = this.getThreadLocalRequest().getSession();
		try {
			PersonneImpl personneImpl = pm.getObjectById(PersonneImpl.class,
					(String) session.getAttribute("login"));
			if (!hasFriend(friendName, personneImpl)) {
				Key keyFriend = KeyFactory.createKey(
						PersonneImpl.class.getSimpleName(), friendName);
				personneImpl.addFriend(keyFriend);
				res = true;
			} else {
				res = false;
			}
			pm.makePersistent(personneImpl);
		} finally {
			pm.close();
		}
		return res;
	}

	private boolean hasFriend(String friendName, PersonneImpl personne) {
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();

		try {
			for (Key key : personne.getListeAmis()) {
				PersonneImpl ami = pm.getObjectById(PersonneImpl.class, key);
				if (ami.getLogin().equals(friendName)) {
					return true;
				}
			}
		} finally {
			pm.close();
		}

		return false;
	}

	@Override
	public List<PersonneCli> getFriends() {
		List<PersonneCli> res = new ArrayList<PersonneCli>();
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		try {
			PersonneImpl personneImpl = getSessionLogin();
			List<Key> listeAmis = personneImpl.getListeAmis();
			for (Key amiKey : listeAmis) {
				PersonneImpl ami = pm.getObjectById(PersonneImpl.class, amiKey);
				res.add(createPersonneCli(ami));
			}
		} finally {
			pm.close();
		}
		return res;
	}

	@Override
	public boolean logout() {
		HttpSession session = this.getThreadLocalRequest().getSession();
		session.removeAttribute("login");
		return true;
	}

	@Override
	public boolean exitGroupe(String groupeName) {
		boolean res = false;
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		try {
			PersonneImpl personneImpl = getSessionLogin();
			GroupesImpl groupeImpl = pm.getObjectById(GroupesImpl.class,
					groupeName);
			groupeImpl.removePersonne(personneImpl);
			pm.makePersistent(personneImpl);
			res = true;
		} finally {
			pm.close();
		}
		return res;
	}

	@Override
	public boolean deleteFriend(String friendName) {
		boolean res = false;

		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		HttpSession session = this.getThreadLocalRequest().getSession();
		try {
			PersonneImpl personneImpl = pm.getObjectById(PersonneImpl.class,
					(String) session.getAttribute("login"));
			Key keyFriend = KeyFactory.createKey(
					PersonneImpl.class.getSimpleName(), friendName);
			personneImpl.removeFriend(keyFriend);
			res = true;
		}finally{
			pm.close();
		}
		return res;
	}
	
	public PersonneImpl getSessionLogin(){
		PersonneImpl res=null;
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		HttpSession session = this.getThreadLocalRequest().getSession();
		try {
			res = pm.getObjectById(PersonneImpl.class, (String) session.getAttribute("login"));		
			
		}finally{
			pm.close();
		}
		
		return res;
	}

	@Override
	public boolean envoyerMessageToAllFriends(Map<String, String> message) {
		PersonneImpl personneLog = getSessionLogin();
		List<Key> listeAmis = personneLog.getListeAmis();
		boolean res = false;
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		try{
			MessagesImpl messagesImpl = new MessagesImpl();
			Key key = KeyFactory.createKey(MessagesImpl.class.getSimpleName(),
					message.get("titre"));
			messagesImpl.setKey(key);
			messagesImpl.setEnvoyeur(personneLog.getLogin());
			messagesImpl.setTitre(message.get("titre"));
			messagesImpl.setMessage(message.get("message"));
			messagesImpl.addPersonne(personneLog);
			for(Key keyAmi : listeAmis){
				PersonneImpl ami = pm.getObjectById(PersonneImpl.class, keyAmi);
				messagesImpl.addPersonne(ami);
			}
			pm.makePersistent(messagesImpl);
			pm.makePersistent(personneLog);
			res = true;
		}finally {
			pm.close();
		}
		return res;
	}

	@Override
	public boolean envoyerMessageToFriend(Map<String, String> message,
			String friendName) {
		PersonneImpl personneLog = getSessionLogin();
		
		boolean res = false;
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		try{
			MessagesImpl messagesImpl = new MessagesImpl();
			Key key = KeyFactory.createKey(MessagesImpl.class.getSimpleName(),
					message.get("titre"));
			messagesImpl.setKey(key);
			messagesImpl.setEnvoyeur(personneLog.getLogin());
			messagesImpl.setTitre(message.get("titre"));
			messagesImpl.setMessage(message.get("message"));
			PersonneImpl ami = pm.getObjectById(PersonneImpl.class,friendName);
			messagesImpl.addPersonne(ami);
			pm.makePersistent(messagesImpl);
			res = true;
		}finally{
			pm.close();
		}
		return res;
	}

	@Override
	public List<MessageCli> seeMessages() {
		List<MessageCli> listTitreMessages = new ArrayList<MessageCli>();
		PersonneImpl personneLog = getSessionLogin();
		List<Key> listMessages = personneLog.getListMessages();
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		try{
			for(Key key : listMessages){
				MessagesImpl message = pm.getObjectById(MessagesImpl.class, key);
				
				listTitreMessages.add(createMessageCli(message));
			}
		}finally{
			pm.close();
		}
		return listTitreMessages;
	}

	private MessageCli createMessageCli(MessagesImpl message) {
		MessageCli messageCli = new MessageCli();
		messageCli.setEnvoyeur(message.getEnvoyeur());
		messageCli.setTitre(message.getTitre());
		messageCli.setMessage(message.getMessage());
		PersistenceManagerFactory pmf = PMF.get();
		PersistenceManager pm = pmf.getPersistenceManager();
		try{
			for(Key key :message.getListPersonnes()){
				PersonneImpl pers = pm.getObjectById(PersonneImpl.class,key);
				messageCli.addPersonne(createPersonneCli(pers));
			}
		}finally{
			pm.close();
		}
		return messageCli;
	}

}
